#include "Structures.h"
#include <stdio.h>
#include <math.h>


double dotPoints( Point3 p1, Point3 p2 )
{
    return p1.x*p2.x + p1.y*p2.y + p1.z*p2.z;
}

void subtractPoints( Point3 p1, Point3 p2, Point3 * result )
{
    result->x = p1.x - p2.x;
    result->y = p1.y - p2.y;
    result->z = p1.z - p2.z;
}

void addPoints( Point3 p1, Point3 p2, Point3 * result )
{
    result->x = p1.x + p2.x;
    result->y = p1.y + p2.y;
    result->z = p1.z + p2.z;
}

void scalePoint( Point3 p1, double factor, Point3 * result )
{
    result->x = p1.x * factor;
    result->y = p1.y * factor;
    result->z = p1.z * factor;
}

void normalize( Point3 * point )
{
    double mag = sqrt( dotPoints(*point, *point) );
    point->x = point->x / mag;
    point->y = point->y / mag;
    point->z = point->z / mag;
}

void reflectVector( Point3 inVector, Point3 normal, Point3 * outVector )
{
    double dot = dotPoints( inVector, normal );
    Point3 result;
    scalePoint( normal, -2 * dot, &result );
    addPoints( result, inVector, outVector );
}

double eulideanDistance( Point3 p1, Point3 p2 )
{
    return sqrt( pow( p1.x - p2.x, 2 ) + pow( p1.y - p2.y, 2 ) + pow( p1.z - p2.z, 2 ) );
}

//inVector is ray into plane
double lightEquation( Point3 inVector, Point3 surfaceLoc, Point3 normal, Point3 lightLoc )
{
    Point3 reflectedVector;
    reflectVector( inVector, normal, &reflectedVector );
    normalize( &reflectedVector );

	double attenuation = ATTENUATION_FACTOR / ( pow(eulideanDistance(surfaceLoc,lightLoc) , 2) );

    Point3 surfaceToLight;
    subtractPoints( lightLoc, surfaceLoc, &surfaceToLight);
    normalize( &surfaceToLight );

    Point3 eyeToSurface = Point3( inVector.x, inVector.y, inVector.z );
    normalize( &eyeToSurface );
    
    double dot1 = dotPoints( surfaceToLight, normal );
    double dot2 = dotPoints( eyeToSurface, reflectedVector ); 

    double light = AMBIENT_LIGHT 
                   + attenuation* DIFFUSE_FACTOR * dot1
                   + attenuation * SPECULAR_FACTOR 
                        * pow( dot2, SPECULAR_POWER );

    if ( dot1 < 0.0001 )
    {
        dot1 =0;
    }

    if (light > 1 )
    {
        light = 1;
    }
    return light;
}

Color4 addColors( Color4 * colors, double * colorPercents, int countColors)
{
    Color4 result(0,0,0,1);
    for (int i =0; i< countColors; i++ )
    {
        result.red += colors[i].red * colorPercents[i];
        result.green += colors[i].green * colorPercents[i];
        result.blue += colors[i].blue * colorPercents[i];
    }
    return result;
}

void addTwoColors( Color4 color, Color4 * myColor)
{
    myColor->red += color.red;
    myColor->green += color.green;
    myColor->blue += color.blue;
}

Color4 multiplyColors( Color4 color1, Color4 color2, double scalar)
{
    Color4 result(0, 0, 0, 1);
    result.red = color1.red *color2.red * scalar;
    result.green = color1.green *color2.green * scalar;
    result.blue = color1.blue * color2.blue * scalar;
    return result;
}